/**
 * @file 这个组件和list-card组件类似，但是list-card不支持column中事件调起和更新，因此单独拆开
 * 如果还有类似需求，可以编写高阶组件将两者合并
 * */
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Checkbox, message, Modal, Select, Table, Tooltip } from 'antd';
import _ from 'lodash';
import moment from 'moment';

import { SiteChangeSvg } from '@containers/console/images';
import { changeSiteKnownStatus, loadChangeAssets } from '@api/asset';
import SystemSettingSvg from '@images/system-setting.svg';

import './index.less';
import '../ListCard/index.less';
import { getColumnsConfig, setColumnsConfig } from '@api/user';

const CheckboxGroup = Checkbox.Group;
const prefixCls = 'site-change-card';
const DASHBOARD_SITE_UPDATE = 'DASHBOARD_SITE_UPDATE';

const TimeRangeMap = {
  1: '今日',
  7: '近7日',
  30: '近30日'
};

const omitConfigKeys = ['_id', 'siteInfo.weight', 'siteInfo'];

class SitesChangeCard extends React.Component {
  static propTypes = {
    setProps: PropTypes.func,
    renderSiteInfo: PropTypes.func,
    getSiteRangeJumper: PropTypes.func,
    getSiteExporter: PropTypes.func,
    className: PropTypes.string
  };
  constructor(props) {
    super(props);
    const entireColumnsKey = this.columns
      .map(item => item.dataIndex)
      .filter(item => item.dataIndex !== '_id');

    this.state = {
      page: 1,
      pageSize: 10,
      count: 0,
      list: [],
      siteChangeCount: 0,
      loading: false,
      timeRange: 7,
      columnsConfigVisible: false,
      indeterminate: false,
      columnsKeys: entireColumnsKey,
      entireColumnsKey,
      columnsCheckAll: true,
      columns: this.columns
    };
  }

  componentDidMount() {
    this.getSiteChangeSites();
    this.getList();
    this.getSiteColumnsConfig();
  }

  getSiteChangeSites = () => {
    const { timeRange } = this.state;
    const { setProps } = this.props;
    const restKeys = [1, 7, 30].filter(key => key !== timeRange);
    for (let key of restKeys) {
      loadChangeAssets({
        pagaition: { page: 1, pageSize: 1 },
        query: {
          created: [
            moment()
              .endOf('day')
              .subtract(key, 'day')
              .format('YYYY-MM-DD HH:mm:ss'),
            moment().format('YYYY-MM-DD HH:mm:ss')
          ]
        }
      }).then(res => {
        const siteChangeCount = _.get(res, 'data.data.count', 0);
        setProps(state => {
          const countMap = _.get(state, 'countMap') || {};
          countMap[`updatedSite${key}`] = siteChangeCount;
          return { countMap };
        });
      });
    }
  };

  getList() {
    const { page, pageSize, timeRange } = this.state;
    const { setProps } = this.props;
    this.setState({ loading: true });

    loadChangeAssets({
      pagaition: { page, pageSize },
      query: {
        created: [
          moment()
            .endOf('day')
            .subtract(timeRange, 'day')
            .format('YYYY-MM-DD HH:mm:ss'),
          moment().format('YYYY-MM-DD HH:mm:ss')
        ]
      },
      sort: {
        by: 'created',
        direction: -1
      }
    }).then(res => {
      const siteChangeCount = _.get(res, 'data.data.count', 0);
      const count = _.get(res, 'data.data.count', 0);
      let list = _.get(res, 'data.data.list', 0);
      list = _.map(list, res => {
        res.tags = res.tagName;
        return res;
      });
      setProps(state => {
        const countMap = _.get(state, 'countMap') || {};
        countMap[`updatedSite${timeRange}`] = siteChangeCount;
        return { countMap };
      });
      this.setState({ count, list, loading: false, siteChangeCount });
    });
  }

  getSiteColumnsConfig = () => {
    const { entireColumnsKey } = this.state;
    getColumnsConfig(DASHBOARD_SITE_UPDATE).then(res => {
      const columnsKeys = _.get(res, 'data.data.columnsConfig.columnsKeys');
      if (columnsKeys && Array.isArray(columnsKeys)) {
        const curColumns = this.columns.filter(
          item => columnsKeys.includes(item.dataIndex) || omitConfigKeys.includes(item.dataIndex)
        );
        this.setState({
          columnsKeys,
          columns: curColumns,
          columnsCheckAll: entireColumnsKey.length === columnsKeys.length,
          indeterminate: entireColumnsKey.length !== columnsKeys.length
        });
      }
    });
  };

  setSiteColumnsConfig = () => {
    const { columnsKeys } = this.state;
    if (!columnsKeys.length) {
      message.warning('最少需要选择一个表头');
      return;
    }
    setColumnsConfig({ key: DASHBOARD_SITE_UPDATE, columnsKeys })
      .then(() => {
        const curColumns = this.columns.filter(
          item => columnsKeys.includes(item.dataIndex) || omitConfigKeys.includes(item.dataIndex)
        );
        this.setState({ columns: curColumns });
      })
      .finally(() => {
        this.setState({ columnsConfigVisible: false });
      });
  };

  // 所有字段如果一行显示不完，需要换行显示，超过3行显示...
  renderPortChange = (detail = {}) => {
    const { name } = detail;

    function generateUpdate(sliceIndex) {
      return _.map(
        detail.update.slice(0, sliceIndex),
        ({ from, to }) =>
          `${name ? name + ': ' : ''}${!_.isEmpty(from) ? from.join('、') : '未知'} 变更为 ${
            !_.isEmpty(to) ? to.join('、') : '未知'
          }`
      ).join('、');
    }

    let text = '';
    if (!_.isEmpty(detail.newAdd)) {
      text += `新增了 ${detail.newAdd.join('、')};`;
    }
    if (!_.isEmpty(detail.remove)) {
      text += `关闭了 ${detail.remove.join('、')};`;
    }
    if (!_.isEmpty(detail.update)) {
      text += generateUpdate(2, true);
    }

    return (
      <div className="port-change-item">
        <Tooltip title={text}>{text}</Tooltip>
      </div>
    );
  };

  columns = [
    {
      title: '权重',
      dataIndex: 'siteInfo.weight'
    },
    {
      title: '资产信息',
      dataIndex: 'siteInfo',
      width: 150,
      render: this.props.renderSiteInfo
    },
    {
      title: 'url变更',
      dataIndex: 'url',
      render: this.renderPortChange
    },
    {
      title: '资产名称变更',
      dataIndex: 'siteName',
      render: this.renderPortChange
    },
    {
      title: 'IP变更',
      dataIndex: 'ip',
      render: this.renderPortChange
    },
    {
      title: '标签变更',
      dataIndex: 'tags',
      render: this.renderPortChange
    },
    {
      title: '其他变更',
      dataIndex: 'customizeAttr',
      render: customizeAttr => {
        if (_.isEmpty(customizeAttr)) {
          return '';
        }
        return (
          <div>
            {customizeAttr.map(detail => this.renderPortChange({ ...detail, name: detail.label }))}
          </div>
        );
      }
    },
    {
      title: '端口变更',
      dataIndex: 'ports',
      render: this.renderPortChange
    },
    {
      title: '服务变更',
      dataIndex: 'servers',
      render: this.renderPortChange
    },
    {
      title: '组件变更',
      dataIndex: 'components',
      render: this.renderPortChange
    },
    {
      title: '资产类型变更',
      dataIndex: 'assetCategories',
      render: this.renderPortChange
    },
    {
      title: '操作系统变更',
      dataIndex: 'os',
      render: this.renderPortChange
    },
    {
      title: '网站标题变更',
      dataIndex: 'titles',
      render: this.renderPortChange
    },
    {
      title: '变更时间',
      dataIndex: 'created',
      render: created => {
        return moment(created).format('YYYY-MM-DD HH:mm:ss');
      }
    },
    {
      title: '操作',
      dataIndex: '_id',
      fixed: 'right',
      render: (id, record) => {
        const { hasKnown } = record;
        return (
          <Button type="link" onClick={() => this.handleSitesChangeStatus(id)} disabled={hasKnown}>
            已知悉
          </Button>
        );
      }
    }
  ];

  rowClassName = record => {
    if (_.get(record, 'hasKnown')) {
      return 'disabled-text';
    }
    return '';
  };

  getOperations = ({ setState, state }) => {
    const timeRange = _.get(state, 'timeRange', 7);
    return [
      <Select
        key="range"
        buttonStyle="solid"
        defaultValue={7}
        style={{ width: 100 }}
        onChange={value => {
          setState({ timeRange: Number(value) });
          this.resertTable();
        }}
        getPopupContainer={triggerNode => triggerNode.parentNode}
      >
        <Select.Option value={1}>今日</Select.Option>
        <Select.Option value={7}>近7日</Select.Option>
        <Select.Option value={30}>近30日</Select.Option>
      </Select>,
      this.props.getSiteExporter({ timeRange: timeRange }, `${TimeRangeMap[timeRange]}变更的资产`),
      <a
        onClick={() => {
          this.setState({ columnsConfigVisible: true });
        }}
        key={'columnsSetting'}
      >
        <img src={SystemSettingSvg} alt="setting" />
      </a>
    ];
  };

  handleSitesChangeStatus = id => {
    changeSiteKnownStatus(id).then(() => {
      this.getList();
    });
  };

  onTableChange = ({ current, pageSize }) => {
    this.setState({ page: current, pageSize }, this.getList);
  };

  resertTable = () => {
    this.setState({ page: 1, pageSize: 10 }, this.getList);
  };

  handleColumnsChange = checkedList => {
    const { entireColumnsKey } = this.state;
    this.setState({
      indeterminate: checkedList.length && checkedList.length < entireColumnsKey.length,
      columnsCheckAll: checkedList.length === entireColumnsKey.length,
      columnsKeys: checkedList
    });
  };

  handleCheckAllChange = e => {
    const { entireColumnsKey } = this.state;
    const checked = e.target.checked;

    this.setState({
      columnsKeys: checked ? entireColumnsKey : [],
      indeterminate: false,
      columnsCheckAll: checked
    });
  };
  render() {
    const {
      list,
      count,
      page,
      pageSize,
      loading,
      timeRange,
      siteChangeCount,
      columnsConfigVisible,
      columnsKeys,
      indeterminate,
      columnsCheckAll,
      columns
    } = this.state;

    const { className } = this.props;

    const operations = this.getOperations({
      state: this.state,
      setState: state => this.setState(state, this.getList)
    });

    return (
      <div className={`list-card list-change-card ${className}`}>
        <div className="list-card-title">
          <img src={SiteChangeSvg} alt="update" style={{ width: '18px' }} />
          <span className="text">
            {`${TimeRangeMap[timeRange || 7]}变更的资产日志`}&nbsp;({siteChangeCount || 0})
          </span>
          {operations}
        </div>
        <Table
          className="data-table site-change-table"
          loading={loading}
          dataSource={list}
          pagination={{
            current: page,
            pageSize,
            style: { height: 40 },
            total: count,
            showQuickJumper: false,
            showTotal: false
          }}
          bordered={false}
          columns={columns}
          onChange={this.onTableChange}
          rowClassName={this.rowClassName}
        />
        <Modal
          visible={columnsConfigVisible}
          className={`${prefixCls}-modal`}
          width={700}
          onCancel={() => {
            this.setState({ columnsConfigVisible: false });
          }}
          onOk={this.setSiteColumnsConfig}
        >
          <div className={`${prefixCls}-modal-all`}>
            <label className={`${prefixCls}-modal-all-label`}>显示字段：</label>
            <Checkbox
              indeterminate={indeterminate}
              checked={columnsCheckAll}
              onChange={this.handleCheckAllChange}
            >
              全部
            </Checkbox>
          </div>
          <div className={`${prefixCls}-modal-detail`}>
            <label className={`${prefixCls}-modal-detail-label`}>自定义：</label>
            <CheckboxGroup
              className={`${prefixCls}-modal-detail-group`}
              options={this.columns
                .filter(item => !omitConfigKeys.includes(item.dataIndex))
                .map(item => {
                  return {
                    label: item.title,
                    value: item.dataIndex
                  };
                })}
              value={columnsKeys}
              onChange={this.handleColumnsChange}
            />
          </div>
        </Modal>
      </div>
    );
  }
}

export default SitesChangeCard;
